﻿using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using WeChatSDK.Common;
using WeChatSDK.Common.Enums.Http;
using WeChatSDK.RequestComponent.Http;
using WeChatSDK.WeChatDto.Conversation.BaseSupport;
using WeChatSDK.WeChatDto.ErrorMessage;
using WeChatSDK.WeChatDto.Request.Http;

namespace WeChatSDK.WeChatServiceComponent.Conversation.BaseSupport
{
    /// <summary>
    /// 微信基础支持服务
    /// </summary>
    public class BaseSupportService
    {
        private readonly HttpHandle httpHandle;
        private const string AccessTokenUrl = @"https://api.weixin.qq.com/cgi-bin/token";

        private static WeChatAccessTokenDto weChatAccessTokenDto;

        public static WeChatAccessTokenDto WeChatAccessTokenDto { get => weChatAccessTokenDto; set => weChatAccessTokenDto = value; }

        public BaseSupportService()
        {
            this.httpHandle = new HttpHandle();
        }

        public WeChatAccessTokenDto CreateAccessToken()
        {
            if (WeChatAccessTokenDto != null)
            {
                DateTime expiresIn = WeChatAccessTokenDto.CreateTime.Value.AddSeconds(WeChatAccessTokenDto.ExpiresIn-500);
                if (expiresIn > DateTime.Now)
                {
                    return WeChatAccessTokenDto;
                }
            }
            WeChatGeneral.OnTakeTokenEvent();
            if (WeChatAccessTokenDto != null&& WeChatAccessTokenDto != default(WeChatAccessTokenDto)) {
                if (WeChatAccessTokenDto.CreateTime.Value.AddSeconds(WeChatAccessTokenDto.ExpiresIn - 500) > DateTime.Now)
                {
                    return WeChatAccessTokenDto;
                }
            }
            WeChatAccessTokenRequestDto weChatAccessTokenRequestDto = new WeChatAccessTokenRequestDto();
            weChatAccessTokenRequestDto.Appid = WeChatInfo.AppId;
            weChatAccessTokenRequestDto.Secret = WeChatInfo.Secret;
            WeChatAccessTokenDto = GetAccessToken(AccessTokenUrl, weChatAccessTokenRequestDto);
            WeChatAccessTokenDto.CreateTime = DateTime.Now;
            GetJSApiTicket(WeChatAccessTokenDto);
            WeChatGeneral.OnChangedTokenEvent(WeChatAccessTokenDto);
            return WeChatAccessTokenDto;
        }

        /// <summary>
        /// 获取AccessToken
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <param name="weChatAccessTokenRequestDto">AccessToken请求对象</param>
        /// <exception cref="WeChatException"></exception>
        /// <returns></returns>
        private WeChatAccessTokenDto GetAccessToken(string url, WeChatAccessTokenRequestDto weChatAccessTokenRequestDto)
        {

            HttpRequestDto httpRequestDto = new HttpRequestDto();
            httpRequestDto.Url = string.Concat(url, string.Format("?{0}", string.Join('&', weChatAccessTokenRequestDto.ToDictionary(true).Select(p => string.Concat(p.Key, "=", p.Value)))));
            httpRequestDto.Method = MethodType.GET;
            httpRequestDto.ContentType = FormatType.JSON;
            HttpResponseDto httpResponseDto = this.httpHandle.HttpSendRequest(httpRequestDto);
            return JsonConvert.DeserializeObject<WeChatAccessTokenDto>(httpResponseDto.ResponseMessage, WeChatGeneral.JsonSerializerSettings);
        }
        /// <summary>
        /// 获取JSAPI票
        /// </summary>
        /// <param name="weChatAccessTokenDto">AccessToken请求对象</param>
        private void GetJSApiTicket(WeChatAccessTokenDto weChatAccessTokenDto)
        {
            HttpRequestDto httpRequestDto = new HttpRequestDto();
            httpRequestDto.Url = string.Format("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi", weChatAccessTokenDto.AccessToken);
            httpRequestDto.Method = MethodType.GET;
            httpRequestDto.ContentType = FormatType.JSON;
            HttpResponseDto httpResponseDto = this.httpHandle.HttpSendRequest(httpRequestDto);
            if (!httpResponseDto.IsError)
            {
                dynamic result = JsonConvert.DeserializeObject<dynamic>(httpResponseDto.ResponseMessage, WeChatGeneral.JsonSerializerSettings);
                weChatAccessTokenDto.JsapiTicket = result.ticket;
            }
        }

        /// <summary>
        /// 获取微信服务器Ip列表
        /// </summary>
        /// <returns></returns>
        public WeChatIpListDto GetWeChatIpList()
        {
            if (WeChatAccessTokenDto != null)
            {
                if (WeChatAccessTokenDto.CreateTime.Value.AddMinutes(WeChatAccessTokenDto.ExpiresIn) < DateTime.Now)
                {
                    CreateAccessToken();
                }
            }
            else
            {
                CreateAccessToken();
            }
            HttpRequestDto httpRequestDto = new HttpRequestDto();
            httpRequestDto.Url = string.Concat("https://api.weixin.qq.com/cgi-bin/getcallbackip", string.Format("?access_token={0}", WeChatAccessTokenDto.AccessToken));
            httpRequestDto.Method = MethodType.GET;
            httpRequestDto.ContentType = FormatType.JSON;
            HttpResponseDto httpResponseDto = this.httpHandle.HttpSendRequest(httpRequestDto);
            return JsonConvert.DeserializeObject<WeChatIpListDto>(httpResponseDto.ResponseMessage, WeChatGeneral.JsonSerializerSettings);
        }

    }
}
